package guda.house.web.action.sys;

import guda.grape.autogen.common.page.BizResult;
import guda.grape.util.Convert;
import guda.house.biz.beans.ImportOwnerInfo;
import guda.house.biz.beans.ImportWaterInfo;
import guda.house.biz.bo.OwnerBO;
import guda.house.biz.constants.CommonResultCode;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.util.IOUtils;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;

/**
 * Created by well on 16/3/10.
 */
@Controller
@RequestMapping(value = "sys/import")
public class ImportWaterAction {

    private final static Logger logger = LoggerFactory.getLogger(ImportOwnerAction.class);

    public static final String OFFICE_EXCEL_2003_POSTFIX = "xls";
    public static final String OFFICE_EXCEL_2010_POSTFIX = "xlsx";

    @Autowired
    private OwnerBO ownerBO;

    @RequestMapping(value = "/importWater.htm", method = RequestMethod.GET)
    public String importOwner() {
        return "sys/import/importWater.vm";
    }


    @RequestMapping(value = "/downWaterTemplate.htm", method = RequestMethod.GET)
    public String downOwnerTemplate(HttpServletResponse response) {

        OutputStream os = null;
        try {
            InputStream resourceAsStream = ImportOwnerAction.class.getResourceAsStream("/xls/water_template.xls");
            if (resourceAsStream == null) {
                return "redirect:/error.htm?code=" + CommonResultCode.UNKOWN_ERROR;
            }

            response.reset();
            String filedisplay = URLEncoder.encode("import_water_template.xls", "UTF-8");
            response.setContentType("application/x-download; charset=UTF-8");
            response.addHeader("Content-Disposition", "attachment; filename=" + filedisplay);
            os = response.getOutputStream();

            byte[] b = new byte[100];
            int len;

            while ((len = resourceAsStream.read(b)) > 0) {
                response.getOutputStream().write(b, 0, len);
            }
            resourceAsStream.close();

        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            if (os != null) {
                IOUtils.closeQuietly(os);
            }

        }

        return "redirect:/error.htm?code=" + CommonResultCode.UNKOWN_ERROR;
    }

    @RequestMapping(value = "/importWater.htm", method = RequestMethod.POST)
    public String importOwner(@RequestParam(value = "file", required = true) MultipartFile file, HttpServletRequest request, ModelMap model) {

        String name = file.getOriginalFilename();
        List<ImportWaterInfo> importWaterInfos = null;
        try {
            if (name.endsWith(OFFICE_EXCEL_2003_POSTFIX)) {
                importWaterInfos = readXls(file.getInputStream());
            } else {
                importWaterInfos = readXlsx(file.getInputStream());
            }
            if (importWaterInfos != null) {
                BizResult bizResult = ownerBO.initWater(importWaterInfos);
                if (bizResult.success) {
                    Integer count = (Integer) bizResult.data.get("ownerCount");
                    return "redirect:/sys/import/importWaterResult.htm?count=" + count;
                } else {
                    return "redirect:/error.htm?code=" + bizResult.code;
                }
            }
        } catch (Exception e) {
            logger.error("", e);
        }
        return "redirect:/error.htm?code=" + CommonResultCode.UNKOWN_ERROR;


    }

    private static String[] fieldArray = new String[]{"villageName",
            "buildingName",
            "unitName",
            "suiteName",
            "type",
            "start",
            "end",
            "recordLast",
            "recordCurrent"};

    private static List<ImportWaterInfo> readXls(InputStream inputStream) throws IOException, NoSuchFieldException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        POIFSFileSystem poifsFileSystem = new POIFSFileSystem(inputStream);
        HSSFWorkbook wb = new HSSFWorkbook(poifsFileSystem);
        int numberOfSheets = wb.getNumberOfSheets();
        List<ImportWaterInfo> resultList = new ArrayList<ImportWaterInfo>(1000);

        HSSFSheet sheetAt = wb.getSheetAt(0);
        int physicalNumberOfRows = sheetAt.getPhysicalNumberOfRows();
        for (int j = 2; j < physicalNumberOfRows; ++j) {
            HSSFRow row = sheetAt.getRow(j);
            if (row == null) {
                continue;
            }
            int physicalNumberOfCells = row.getPhysicalNumberOfCells();
            if (physicalNumberOfCells == 0) {
                continue;
            }
            ImportWaterInfo importWaterInfo = new ImportWaterInfo();
            int m = 0;
            for (String f : fieldArray) {
                if (row.getCell(m) == null) {
                    continue;
                }
                Object val = null;
                Field field = ImportWaterInfo.class.getDeclaredField(f);
                if (field.getType().equals(int.class)) {
                    row.getCell(m).setCellType(Cell.CELL_TYPE_STRING);
                    if(row.getCell(m)!=null && row.getCell(m).getStringCellValue()!=null) {
                        String v = StringUtils.trimWhitespace(row.getCell(m).getStringCellValue());
                        if (v != null) {
                            val = Convert.toInt(v);
                        }
                    }
                } else if (field.getType().equals(Integer.class)) {
                    row.getCell(m).setCellType(Cell.CELL_TYPE_STRING);
                    if(row.getCell(m)!=null && row.getCell(m).getStringCellValue()!=null) {
                        String v = StringUtils.trimWhitespace(row.getCell(m).getStringCellValue());
                        if (v != null) {
                            val = new Integer(Convert.toInt(v));
                        }
                    }
                } else if (field.getType().equals(java.util.Date.class)) {
                    if(row.getCell(m)!=null) {
                        val = (row.getCell(m).getDateCellValue());
                    }
                } else {
                    row.getCell(m).setCellType(Cell.CELL_TYPE_STRING);
                    if(row.getCell(m)!=null && row.getCell(m).getStringCellValue()!=null) {
                        val = StringUtils.trimWhitespace(row.getCell(m).getStringCellValue()).toLowerCase();
                    }
                }
                if(val != null) {

                    String firstLetter = f.substring(0, 1).toUpperCase();
                    String setMethodName = "set" + firstLetter
                            + f.substring(1);
                    Method setMethod = ImportOwnerInfo.class.getMethod(setMethodName,
                            new Class[]{field.getType()});
                    setMethod.invoke(importWaterInfo, new Object[]{val});
                }
                m++;
            }
            if(importWaterInfo.getStart() == null || importWaterInfo.getEnd() ==null||
                    importWaterInfo.getType() == null
                    ||importWaterInfo.getRecordCurrent() == null
                    ||importWaterInfo.getRecordLast() == null){
                throw new RuntimeException("数据缺少");

            }
            resultList.add(importWaterInfo);
        }

        return resultList;
    }

    private static List<ImportWaterInfo> readXlsx(InputStream inputStream) throws Exception {

        XSSFWorkbook xssfWorkbook = new XSSFWorkbook(inputStream);
        List<ImportWaterInfo> resultList = new ArrayList<ImportWaterInfo>(1000);

        XSSFSheet xssfSheet = xssfWorkbook.getSheetAt(0);
        if (xssfSheet == null) {
            return resultList;
        }
        for (int rowNum = 2; rowNum <= xssfSheet.getLastRowNum(); rowNum++) {
            XSSFRow row = xssfSheet.getRow(rowNum);
            if (row == null) {
                continue;
            }
            int physicalNumberOfCells = row.getPhysicalNumberOfCells();
            if (physicalNumberOfCells == 0) {
                continue;
            }
            ImportWaterInfo importWaterInfo = new ImportWaterInfo();
            int m = 0;
            for (String f : fieldArray) {
                if (row.getCell(m) == null) {
                    continue;
                }
                Object val = null;
                Field field = ImportWaterInfo.class.getDeclaredField(f);
                if (field.getType().equals(int.class)) {
                    row.getCell(m).setCellType(Cell.CELL_TYPE_STRING);
                    if(row.getCell(m)!=null && row.getCell(m).getStringCellValue()!=null) {
                        String v = StringUtils.trimWhitespace(row.getCell(m).getStringCellValue());
                        if (v != null) {
                            val = Convert.toInt(v);
                        }
                    }
                } else if (field.getType().equals(Integer.class)) {
                    row.getCell(m).setCellType(Cell.CELL_TYPE_STRING);
                    if(row.getCell(m)!=null && row.getCell(m).getStringCellValue()!=null) {
                        String v = StringUtils.trimWhitespace(row.getCell(m).getStringCellValue());
                        if (v != null) {
                            val = new Integer(Convert.toInt(v));
                        }
                    }
                } else if (field.getType().equals(java.util.Date.class)) {
                    if(row.getCell(m)!=null) {
                        val = (row.getCell(m).getDateCellValue());
                    }
                } else {
                    row.getCell(m).setCellType(Cell.CELL_TYPE_STRING);
                    if(row.getCell(m)!=null && row.getCell(m).getStringCellValue()!=null) {
                        val = StringUtils.trimWhitespace(row.getCell(m).getStringCellValue()).toLowerCase();
                    }
                }
                if(val != null) {

                    String firstLetter = f.substring(0, 1).toUpperCase();
                    String setMethodName = "set" + firstLetter
                            + f.substring(1);
                    Method setMethod = ImportOwnerInfo.class.getMethod(setMethodName,
                            new Class[]{field.getType()});
                    setMethod.invoke(importWaterInfo, new Object[]{val});
                }
                m++;
            }
            resultList.add(importWaterInfo);
        }


        return resultList;
    }
}
